package com.thundern.tdcrawler.model;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.thundern.tdcrawler.selectable.Html;
import com.thundern.tdcrawler.selectable.Json;
import com.thundern.tdcrawler.selectable.Selectable;
import com.thundern.tdcrawler.urls.UrlUtils;

public class Page {
	
	 private Request request;	 
	 private ResultItems resultItems = new ResultItems();
	 private Html html;
	 private Json json;
	 private String rawText;
	 private Selectable url;
	 private int statusCode;
	 private boolean needCycleRetry;
	 private List<Request> targetRequests = new ArrayList<Request>();
	 

	    public Page() {
	    }

	    public Page setSkip(boolean skip) {
	        resultItems.setSkip(skip);
	        return this;
	    }

	    /**
	     * store extract results
	     *
	     * @param key
	     * @param field
	     */
	    public void putField(String key, Object field) {
	        resultItems.put(key, field);
	    }

	    /**
	     * get html content of page
	     *
	     * @return html
	     */
	    public Html getHtml() {
	        if (html == null) {
	            html = new Html(UrlUtils.fixAllRelativeHrefs(rawText, request.getUrl()));
	        }
	        return html;
	    }

	    /**
	     * get json content of page
	     *
	     * @return json
	     * @since 0.5.0
	     */
	    public Json getJson() {
	        if (json == null) {
	            json = new Json(rawText);
	        }
	        return json;
	    }

	    /**
	     * @param html
	     * @deprecated since 0.4.0
	     * The html is parse just when first time of calling {@link #getHtml()}, so use {@link #setRawText(String)} instead.
	     */
	    public void setHtml(Html html) {
	        this.html = html;
	    }

	    public List<Request> getTargetRequests() {
	        return targetRequests;
	    }

	    /**
	     * add urls to fetch
	     *
	     * @param requests
	     */
	    public void addTargetRequests(List<String> requests) {
	        synchronized (targetRequests) {
	            for (String s : requests) {
	                if (StringUtils.isBlank(s) || s.equals("#") || s.startsWith("javascript:")) {
	                    continue;
	                }
	                s = UrlUtils.canonicalizeUrl(s, url.toString());
	                targetRequests.add(new Request(s));
	            }
	        }
	    }

	    /**
	     * add urls to fetch
	     *
	     * @param requests
	     */
	    public void addTargetRequests(List<String> requests, long priority) {
	        synchronized (targetRequests) {
	            for (String s : requests) {
	                if (StringUtils.isBlank(s) || s.equals("#") || s.startsWith("javascript:")) {
	                    continue;
	                }
	                s = UrlUtils.canonicalizeUrl(s, url.toString());
	                targetRequests.add(new Request(s).setPriority(priority));
	            }
	        }
	    }

	    /**
	     * add url to fetch
	     *
	     * @param requestString
	     */
	    public void addTargetRequest(String requestString) {
	        if (StringUtils.isBlank(requestString) || requestString.equals("#")) {
	            return;
	        }
	        synchronized (targetRequests) {
	            requestString = UrlUtils.canonicalizeUrl(requestString, url.toString());
	            targetRequests.add(new Request(requestString));
	        }
	    }

	    /**
	     * add requests to fetch
	     *
	     * @param request
	     */
	    public void addTargetRequest(Request request) {
	        synchronized (targetRequests) {
	            targetRequests.add(request);
	        }
	    }

	    /**
	     * get url of current page
	     *
	     * @return url of current page
	     */
	    public Selectable getUrl() {
	        return url;
	    }

	    public void setUrl(Selectable url) {
	        this.url = url;
	    }

	    /**
	     * get request of current page
	     *
	     * @return request
	     */
	    public Request getRequest() {
	        return request;
	    }

	    public boolean isNeedCycleRetry() {
	        return needCycleRetry;
	    }

	    public void setNeedCycleRetry(boolean needCycleRetry) {
	        this.needCycleRetry = needCycleRetry;
	    }

	    public void setRequest(Request request) {
	        this.request = request;
	        this.resultItems.setRequest(request);
	    }

	    public ResultItems getResultItems() {
	        return resultItems;
	    }

	    public int getStatusCode() {
	        return statusCode;
	    }

	    public void setStatusCode(int statusCode) {
	        this.statusCode = statusCode;
	    }

	    public String getRawText() {
	        return rawText;
	    }

	    public Page setRawText(String rawText) {
	        this.rawText = rawText;
	        return this;
	    }

	    @Override
	    public String toString() {
	        return "Page{" +
	                "request=" + request +
	                ", resultItems=" + resultItems +
	                ", rawText='" + rawText + '\'' +
	                ", url=" + url +
	                ", statusCode=" + statusCode +
	                ", targetRequests=" + targetRequests +
	                '}';
	    }
	 

	 
}
